package com.size.check;

import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class SizeCheckTask implements Callable<Set<SizeModel>> {

    public static String[] TYPE_FILE = {
            ".jpeg", ".png", ".jpg", ".txt", ".gif", ".json", ".ttf", ".otf", ".dat"
    };
    private final String rootPath;
    private final long smallestSize;

    public SizeCheckTask(String rootPath, long smallestSize) {
        this.rootPath = rootPath;
        this.smallestSize = smallestSize;
    }

    public static Set<SizeModel> startCheck(String rootPath, long smallestSize) {

        SizeCheckTask checkTask = new SizeCheckTask(rootPath, smallestSize);
        try {
            Future<Set<SizeModel>> submit = Executors.newSingleThreadExecutor().submit(checkTask);
            Set<SizeModel> fileEntries = submit.get();
            return fileEntries;
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public Set<SizeModel> findAllResources(String rootPath, long smallestSize) {

        Set<SizeModel> sizeModes = new HashSet<>();

        if (rootPath == null || rootPath.length() == 0) {
            return sizeModes;
        }
        File f = new File(rootPath);
        if (!f.exists()) {
            return sizeModes;
        }
        Stack<String> stack = new Stack<>();
        stack.push(rootPath);

        while (!stack.empty()) {

            String pop = stack.pop();
            if (pop == null || pop.length() == 0) continue;
            File popFile = new File(pop);

            if (popFile.isFile()) {

                String absolutePath = popFile.getAbsolutePath();
                SizeModel sizeModel = filterResource(rootPath, absolutePath, smallestSize);

                if (sizeModel != null) {
                    sizeModes.add(sizeModel);
                }

            } else {
                File[] list = popFile.listFiles();
                if (list == null || list.length == 0) continue;
                for (int i = 0; i < list.length; i++) {
                    String absolutePath = list[i].getAbsolutePath();
                    if (canExclude(absolutePath)) continue;
                    stack.push(absolutePath);
                }
            }
        }

        return sizeModes;

    }

    private SizeModel filterResource(String rootPath, String absolutePath, long smallestSize) {

        String[] subfixes = TYPE_FILE;

        for (String subfix : subfixes) {
            if (!absolutePath.endsWith(subfix)) {
                continue;
            }
            File f = new File(absolutePath);
            if (!f.exists()) continue;

            long length = f.length();

            if (length < smallestSize) continue;

            SizeModel sizeModel = new SizeModel();
            sizeModel.path = absolutePath.substring(rootPath.length());
            sizeModel.size = length;
            return sizeModel;
        }
        return null;
    }

    public static boolean canExclude(String absolutePath) {
        if (absolutePath.contains("/.idea")) return true;
        if (absolutePath.contains("/.gradle")) return true;
        if (absolutePath.contains("/.setting")) return true;
        if (absolutePath.contains("/build")) return true;
        if (absolutePath.contains("/gradle")) return true;
        if (absolutePath.endsWith(".bat")) return true;
        if (absolutePath.endsWith(".sh")) return true;
        if (absolutePath.endsWith(".iml")) return true;
        return false;
    }


    @Override
    public Set<SizeModel> call() {

        Set<SizeModel> allResources = findAllResources(this.rootPath, this.smallestSize);
        return allResources;
    }
}
